//
//  ContentView.swift
//  BounceDemo
//
//  Created by 祝昆磊主系统 on 2025/5/17.
//

//  ContentView.swift
//  BounceDemo
//  Created by ChatGPT helper。

//
//  ContentView5.swift    ← 建议改成一个全新文件名
//  BounceDemo
//
//  Created 2025/5/17
//

import SwiftUI
import UIKit           // 震动反馈
import SceneKit

//======================================================
// MARK: - 1. 震动管理：10 种拟物震动"频率"方案
//======================================================

/// 描述一条"震动模式"
struct HapticPattern {
    let generator: UIFeedbackGenerator       // 反馈对象
    let minInterval: TimeInterval            // 连续触发的最小间隔（秒）
    /// 触发一次（可调节强度，仅impact类型支持）
    func play(strength: Double = 1.0) {
        switch generator {
        case let g as UIImpactFeedbackGenerator:
            if #available(iOS 13.0, *) {
                g.impactOccurred(intensity: CGFloat(strength))
            } else {
                g.impactOccurred()
            }
        case let g as UINotificationFeedbackGenerator:
            g.notificationOccurred(.success)
        case let g as UISelectionFeedbackGenerator:
            g.selectionChanged()
        default: break
        }
    }
}

/// 10 个不同"频率 + 触感"方案（索引 0-9）
enum HapticBank {
    static let patterns: [HapticPattern] = [
        .init(generator: UIImpactFeedbackGenerator(style: .soft),    minInterval: 0.35), // 弹跳(软)
        .init(generator: UIImpactFeedbackGenerator(style: .light),   minInterval: 0.28), // 脉冲(轻)
        .init(generator: UIImpactFeedbackGenerator(style: .medium),  minInterval: 0.22), // 波浪(中)
        .init(generator: UIImpactFeedbackGenerator(style: .rigid),   minInterval: 0.18), // 喷泉(脆)
        .init(generator: UIImpactFeedbackGenerator(style: .heavy),   minInterval: 0.14), // 瀑布(重)
        .init(generator: UINotificationFeedbackGenerator(),          minInterval: 0.60), // 鼓点(成功)
        .init(generator: UINotificationFeedbackGenerator(),          minInterval: 0.60), // 心跳(警告)
        .init(generator: UINotificationFeedbackGenerator(),          minInterval: 0.60), // 雷鸣(错误)
        .init(generator: UISelectionFeedbackGenerator(),             minInterval: 0.12), // 涌动(拨轮)
        .init(generator: UIImpactFeedbackGenerator(style: .heavy),   minInterval: 0.08)  // 环形(极速)
    ]
}

//======================================================
// MARK: - 2. 根视图
//======================================================

struct ContentView: View {

    // 10 种拟物名称
    let vibrationStyles = ["弹跳","脉冲","波浪","喷泉","瀑布",
                           "鼓点","心跳","雷鸣","涌动","环形"]

    // 震动强度标签
    let hapticStrengthLabels = ["极弱", "较弱", "适中", "较强", "极强"]

    // Slider & 文字状态
    @State private var sliderValue:   Double = 0
    @State private var selectedStyle: Int    = 0
    @State private var lastHapticStep: Int   = 0
    @State private var hapticCount: Int = 0 // 震动次数计数器
    @State private var hapticStrength: Double = 1.0 // 震动强度

    private func strengthLabel(for value: Double) -> String {
        let levels = hapticStrengthLabels.count
        let idx = min(max(Int((value-0.2)/0.2), 0), levels-1)
        return hapticStrengthLabels[idx]
    }

    var body: some View {
        ZStack {
            // 背景渐变
            LinearGradient(
                gradient: Gradient(colors: [
                    Color(red: 247/255, green: 246/255, blue: 242/255),
                    Color(red: 195/255, green: 208/255, blue: 217/255),
                    Color(red: 165/255, green: 195/255, blue: 170/255)]),
                startPoint: .topLeading, endPoint: .bottomTrailing)
            .ignoresSafeArea()

            VStack(spacing: 46) {

                // 1) 真实3D万向球体
                Ball3DView(currentStyle: $selectedStyle, hapticStrength: hapticStrength, onHaptic: { hapticCount += 1 })

                // 震动次数显示
                Text("震动次数：\(hapticCount)")
                    .font(.system(size: 22, weight: .medium, design: .rounded))
                    .foregroundColor(Color(red: 93/255, green: 92/255, blue: 87/255).opacity(0.80))

                // 2) 标题
                Text(vibrationStyles[selectedStyle])
                    .font(.system(size: 44, weight: .heavy, design: .rounded))
                    .foregroundColor(Color(red: 93/255, green: 92/255, blue: 87/255))
                    .shadow(color: .white.opacity(0.13), radius: 1, x: 1, y: 1.2)

                // 3) 滑杆
                SliderView1(sliderValue:    $sliderValue,
                           selectedStyle:  $selectedStyle,
                           lastHapticStep: $lastHapticStep,
                           styles: vibrationStyles,
                           hapticStrength: hapticStrength)

                Spacer()

                VStack(alignment: .center, spacing: 6) {
                    Text(strengthLabel(for: hapticStrength))
                        .font(.system(size: 18, weight: .bold))
                        .foregroundColor(.blue)
                        .padding(.bottom, 2)
                    Text("震动强度")
                        .font(.system(size: 18, weight: .medium))
                        .foregroundColor(.gray)
                    Slider(value: $hapticStrength, in: 0.2...1.0)
                        .accentColor(Color(red: 126/255, green: 160/255, blue: 183/255))
                }
                .padding(.horizontal, 24)
                .padding(.bottom, 30)
            }
            .padding(.top, 60)
        }
    }
}

//======================================================
// MARK: - 3. 3D 万向圆球视图（SceneKit实现，完美配色）
//======================================================

struct Ball3DView: View {
    @Binding var currentStyle: Int
    var hapticStrength: Double
    var onHaptic: (() -> Void)? = nil

    @State private var scene = SCNScene()
    @State private var sphereNode = SCNNode()
    @State private var lastImpact: Date = .distantPast
    @State private var totalX: Float = 0
    @State private var totalY: Float = 0
    @State private var scale: CGFloat = 1.0
    // --- 拖动惯性相关状态 ---
    @State private var velocityX: Float = 0
    @State private var velocityY: Float = 0
    @State private var lastDragValue: DragGesture.Value? = nil
    @State private var inertiaActive: Bool = false
    @State private var lastDragTranslation: CGSize = .zero
    @State private var dragStartTime: Date? = nil

    // 拖动惯性动画，让球旋转“极致丝滑”
    func animateInertia() {
        let threshold: Float = 0.0007
        let friction: Float = 0.7   //摩擦系数   1表示没有摩擦力  越小 摩擦力越大  可用于调节惯性转动速度
        guard inertiaActive, (abs(velocityX) > threshold || abs(velocityY) > threshold) else {
            inertiaActive = false
            return
        }
        totalX += velocityX
        totalY += velocityY
        SCNTransaction.begin()
        SCNTransaction.animationDuration = 0.28
        sphereNode.eulerAngles.x = totalX
        sphereNode.eulerAngles.y = totalY
        SCNTransaction.commit()

        // 震动动画
        let pattern = HapticBank.patterns[currentStyle]
        let now = Date()
        if now.timeIntervalSince(lastImpact) > pattern.minInterval {
            pattern.play(strength: hapticStrength)
            lastImpact = now
            onHaptic?()
            withAnimation(.interactiveSpring(response: 0.22, dampingFraction: 0.67)) {
                scale = 1.17
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.18) {
                withAnimation(.interactiveSpring(response: 0.33, dampingFraction: 0.67)) {
                    scale = 1.0
                }
            }
        }

        velocityX *= friction
        velocityY *= friction
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.012) {
            animateInertia()
        }
    }

    var body: some View {
        ZStack {
            // 球窝底座
            Circle()
                .fill(
                    LinearGradient(
                        gradient: Gradient(colors: [
                            Color(red: 193/255, green: 208/255, blue: 217/255),
                            Color(red: 165/255, green: 195/255, blue: 170/255)
                        ]),
                        startPoint: .top, endPoint: .bottom)
                )
                .frame(width: 140, height: 140)//调整底座大小，目前是被遮盖的，用不上底座
                .overlay(
                    Circle()
                        .stroke(Color.white.opacity(0.17), lineWidth: 7)
                        .blur(radius: 1.1)
                )
                .shadow(color: Color(red: 123/255, green: 139/255, blue: 151/255).opacity(0.08),
                        radius: 13, x: 0, y: 11)
                .shadow(color: .black.opacity(0.06), radius: 24, x: 0, y: 13)
                .offset(y: 2)

            // 3D 球体
            SceneView(
                scene: scene,
                pointOfView: nil,
                options: [],
                preferredFramesPerSecond: 60,
                antialiasingMode: .multisampling4X
            )
            .frame(width: 260, height: 260)//调整圆球大小
            .scaleEffect(scale)
            .animation(.interactiveSpring(response: 0.47, dampingFraction: 0.66, blendDuration: 0.18), value: scale)
            .clipShape(Circle())
            .background(Color.clear)
            .onAppear { setupScene() }
            .gesture(
                DragGesture()
                    .onChanged { value in
                        // translation: 手指本次拖动的"位移"
                        let angleScale: Float = .pi / 360 // 1080pt手势滑动才转一圈
                        let dx = Float(value.translation.width) * angleScale
                        let dy = Float(value.translation.height) * angleScale
                        // 只根据 translation 暂时旋转，不修改 total
                        SCNTransaction.begin()
                        SCNTransaction.animationDuration = 0.21
                        // 修改旋转方向：让球体跟随手指移动方向
                        sphereNode.eulerAngles.x = totalX + dy    // 垂直滑动影响x轴旋转，方向相同
                        sphereNode.eulerAngles.y = totalY + dx    // 水平滑动影响y轴旋转，方向相反
                        SCNTransaction.commit()

                        // 震动、放大动画
                        let pattern = HapticBank.patterns[currentStyle]
                        if Date().timeIntervalSince(lastImpact) > pattern.minInterval {
                            pattern.play(strength: hapticStrength)
                            lastImpact = Date()
                            onHaptic?()
                            withAnimation(.interactiveSpring(response: 0.22, dampingFraction: 0.67)) {
                                scale = 1.17
                            }
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.18) {
                                withAnimation(.interactiveSpring(response: 0.33, dampingFraction: 0.67)) {
                                    scale = 1.0
                                }
                            }
                        }
                    }
                    .onEnded { value in
                        // 拖动结束，把这次 translation 累加到总角度
                        let angleScale: Float = .pi / 360 // 1080pt手势滑动才转一圈
                        let dx = Float(value.translation.width) * angleScale
                        let dy = Float(value.translation.height) * angleScale
                        totalX += dy
                        totalY += dx

                        // 计算拖动速度（惯性动画起点以 totalX/totalY 为准）
                        let endTime = value.time
                        let startTime = dragStartTime ?? endTime
                        let dragDuration = max(endTime.timeIntervalSince(startTime), 0.01)
                        velocityX = dy / Float(dragDuration) * 0.007 // 惯性缩放调节系数（更柔和）
                        velocityY = dx / Float(dragDuration) * 0.007
                        dragStartTime = nil

                        if !inertiaActive {
                            inertiaActive = true
                            animateInertia()
                        }
                    }
            )
        }
    }

    /// 渐变贴图（球中心不用白色，而用淡蓝灰，边缘更暗，带羽化）
    func makeGradientTexture() -> UIImage {
        let size = CGSize(width: 800, height: 800)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        let ctx = UIGraphicsGetCurrentContext()!

        // 主渐变：中心淡蓝灰 → 四周加重蓝灰
        let mainColors = [
            UIColor(red: 160/255, green: 185/255, blue: 210/255, alpha: 1).cgColor,  // 中心淡蓝灰
            UIColor(red: 163/255, green: 199/255, blue: 210/255, alpha: 1).cgColor,  // 中间蓝灰
            UIColor(red: 126/255, green: 160/255, blue: 183/255, alpha: 0.98).cgColor, // 深蓝
            UIColor(red: 126/255, green: 160/255, blue: 183/255, alpha: 0.80).cgColor, // 更透明
            UIColor(red: 126/255, green: 160/255, blue: 183/255, alpha: 0.40).cgColor, // 羽化
            UIColor(red: 126/255, green: 160/255, blue: 183/255, alpha: 0.12).cgColor  // 更羽化
        ]
        let locations: [CGFloat] = [0.0, 0.45, 0.82, 0.90, 0.98, 1.0]
        let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: mainColors as CFArray, locations: locations)!
        ctx.drawRadialGradient(
            gradient,
            startCenter: CGPoint(x: size.width*0.38, y: size.height*0.30),//控制圆球上的白色圆形位置
            startRadius: size.width*0.00,//控制圆球上的白色圆形大小
            endCenter: CGPoint(x: size.width/2, y: size.height/2),
            endRadius: size.width*2.50,//控制长条白色大小
            options: [])

        // 小高光点，左上（不要大面积纯白）
        ctx.setFillColor(UIColor.white.withAlphaComponent(0.15).cgColor)
        ctx.addEllipse(in: CGRect(x: size.width*0.18, y: size.height*0.15, width: size.width*0.13, height: size.height*0.09))
        ctx.fillPath()

        // 边缘高光线
        ctx.setStrokeColor(UIColor(red: 180/255, green: 210/255, blue: 242/255, alpha: 0.12).cgColor)
        ctx.setLineWidth(size.width * 0.022)
        ctx.addEllipse(in: CGRect(x: size.width*0.11, y: size.height*0.11, width: size.width*0.78, height: size.height*0.78))
        ctx.strokePath()

        // 内部淡蓝反光
        ctx.setFillColor(UIColor(red: 150/255, green: 215/255, blue: 255/255, alpha: 0.09).cgColor)
        ctx.addEllipse(in: CGRect(x: size.width*0.53, y: size.height*0.58, width: size.width*0.12, height: size.height*0.09))
        ctx.fillPath()

        // 底部蓝灰阴影
        ctx.setFillColor(UIColor(red: 126/255, green: 160/255, blue: 183/255, alpha: 0.13).cgColor)
        ctx.addEllipse(in: CGRect(x: size.width*0.45, y: size.height*0.78, width: size.width*0.14, height: size.height*0.07))
        ctx.fillPath()
        
        // 添加噪点质感
        for _ in 0..<112000 {
            let x = CGFloat.random(in: 0..<size.width)
            let y = CGFloat.random(in: 0..<size.height)
            let alpha = CGFloat.random(in: 0.045...0.10)
            let radius = CGFloat.random(in: 0.5...1.5)
            let orangeDot = UIColor(white: 1.0, alpha: alpha)  // 亮点
            ctx.setFillColor(orangeDot.cgColor)
            ctx.addEllipse(in: CGRect(x: x, y: y, width: radius, height: radius))
            ctx.fillPath()
        }
        
        for _ in 0..<112000 {
            let x = CGFloat.random(in: 0..<size.width)
            let y = CGFloat.random(in: 0..<size.height)
            let bright = CGFloat.random(in: 0.85...1.15)
            let base = UIColor(red: 250/255*bright, green: 194/255*bright, blue: 37/255*bright, alpha: 0.08)
            ctx.setFillColor(base.cgColor)
            ctx.addEllipse(in: CGRect(x: x, y: y, width: CGFloat.random(in: 0.5...1.2), height: CGFloat.random(in: 0.5...1.2)))
            ctx.fillPath()
        }
        
        // 画五角星函数（可复用）
        func drawStar(center: CGPoint, radius: CGFloat, context: CGContext, color: UIColor) {
            let points = 5
            let path = UIBezierPath()
            for i in 0..<points * 2 {
                let angle = CGFloat(i) * .pi / CGFloat(points)
                let r = (i % 2 == 0) ? radius : radius * 0.42
                let x = center.x + r * sin(angle)
                let y = center.y - r * cos(angle)
                if i == 0 {
                    path.move(to: CGPoint(x: x, y: y))
                } else {
                    path.addLine(to: CGPoint(x: x, y: y))
                }
            }
            path.close()
            context.setFillColor(color.cgColor)
            context.addPath(path.cgPath)
            context.fillPath()
        }

        // 在渐变贴图最后加星星
        let starColor = UIColor(red: 250/255, green: 226/255, blue: 53/255, alpha: 0.93)
        drawStar(center: CGPoint(x: size.width*0.52, y: size.height*0.33), radius: 22, context: ctx, color: starColor)
        drawStar(center: CGPoint(x: size.width*0.28, y: size.height*0.42), radius: 13, context: ctx, color: starColor)
        drawStar(center: CGPoint(x: size.width*0.73, y: size.height*0.66), radius: 10, context: ctx, color: starColor)
        drawStar(center: CGPoint(x: size.width*0.37, y: size.height*0.70), radius: 14, context: ctx, color: starColor)
        drawStar(center: CGPoint(x: size.width*0.60, y: size.height*0.60), radius: 17, context: ctx, color: starColor)
        
        let str = "Hello!"
        let font = UIFont.systemFont(ofSize: 42, weight: .bold)
        let attr: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: UIColor(red: 50/255, green: 120/255, blue: 190/255, alpha: 0.70)
        ]
        let text = NSAttributedString(string: str, attributes: attr)
        text.draw(at: CGPoint(x: size.width*0.3, y: size.height*0.6))

        // ------ 1. 爱心 ------
        let heartPath = UIBezierPath()
        let centerHeart = CGPoint(x: size.width*0.32, y: size.height*0.69)
        heartPath.move(to: CGPoint(x: centerHeart.x, y: centerHeart.y))
        heartPath.addCurve(to: CGPoint(x: centerHeart.x - 30, y: centerHeart.y - 30),
                           controlPoint1: CGPoint(x: centerHeart.x - 10, y: centerHeart.y + 18),
                           controlPoint2: CGPoint(x: centerHeart.x - 40, y: centerHeart.y))
        heartPath.addArc(withCenter: CGPoint(x: centerHeart.x - 18, y: centerHeart.y - 34), radius: 14,
                         startAngle: .pi, endAngle: 0, clockwise: true)
        heartPath.addArc(withCenter: CGPoint(x: centerHeart.x + 18, y: centerHeart.y - 34), radius: 14,
                         startAngle: .pi, endAngle: 0, clockwise: true)
        heartPath.addCurve(to: CGPoint(x: centerHeart.x, y: centerHeart.y),
                           controlPoint1: CGPoint(x: centerHeart.x + 40, y: centerHeart.y),
                           controlPoint2: CGPoint(x: centerHeart.x + 10, y: centerHeart.y + 18))
        ctx.setFillColor(UIColor(red: 255/255, green: 104/255, blue: 172/255, alpha: 0.36).cgColor)
        ctx.addPath(heartPath.cgPath)
        ctx.fillPath()

        // ------ 2. 太阳状旋转金色线 ------
        let sunCenter = CGPoint(x: size.width*0.69, y: size.height*0.23)
        let sunR: CGFloat = 24
        for i in 0..<18 {
            let angle = CGFloat(i) * (.pi * 2 / 18)
            let inner = CGPoint(x: sunCenter.x + sunR * cos(angle),
                                y: sunCenter.y + sunR * sin(angle))
            let outer = CGPoint(x: sunCenter.x + sunR * 1.7 * cos(angle),
                                y: sunCenter.y + sunR * 1.7 * sin(angle))
            ctx.setStrokeColor(UIColor(red: 255/255, green: 210/255, blue: 60/255, alpha: 0.47).cgColor)
            ctx.setLineWidth(3.0)
            ctx.move(to: inner)
            ctx.addLine(to: outer)
            ctx.strokePath()
        }
        ctx.setFillColor(UIColor(red: 255/255, green: 220/255, blue: 80/255, alpha: 0.42).cgColor)
        ctx.addArc(center: sunCenter, radius: sunR, startAngle: 0, endAngle: .pi * 2, clockwise: true)
        ctx.fillPath()

        // ------ 3. 彩虹色极光弧线 ------
        let aurora = UIBezierPath()
        aurora.move(to: CGPoint(x: size.width*0.18, y: size.height*0.16))
        aurora.addCurve(to: CGPoint(x: size.width*0.85, y: size.height*0.19),
                        controlPoint1: CGPoint(x: size.width*0.34, y: size.height*0.03),
                        controlPoint2: CGPoint(x: size.width*0.64, y: size.height*0.33))
        let auroraGradientColors = [
            UIColor(red: 120/255, green: 245/255, blue: 255/255, alpha: 0.25).cgColor,
            UIColor(red: 180/255, green: 120/255, blue: 255/255, alpha: 0.28).cgColor,
            UIColor(red: 255/255, green: 210/255, blue: 130/255, alpha: 0.24).cgColor
        ]
        ctx.saveGState()
        ctx.addPath(aurora.cgPath)
        ctx.setLineWidth(19.0)
        ctx.replacePathWithStrokedPath()
        ctx.clip()
        let auroraGradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: auroraGradientColors as CFArray, locations: [0.0, 0.5, 1.0])!
        ctx.drawLinearGradient(auroraGradient,
            start: CGPoint(x: size.width*0.18, y: size.height*0.16),
            end: CGPoint(x: size.width*0.85, y: size.height*0.19),
            options: [])
        ctx.restoreGState()

        // ------ 4. 蓝白气泡 ------
        let bubble1 = CGRect(x: size.width*0.74, y: size.height*0.75, width: size.width*0.08, height: size.width*0.08)
        let bubble2 = CGRect(x: size.width*0.53, y: size.height*0.79, width: size.width*0.05, height: size.width*0.05)
        let bubbleGradientColors = [
            UIColor(red: 180/255, green: 220/255, blue: 255/255, alpha: 0.85).cgColor,
            UIColor(red: 220/255, green: 245/255, blue: 255/255, alpha: 0.37).cgColor,
            UIColor.white.withAlphaComponent(0.13).cgColor
        ]
        for bubble in [bubble1, bubble2] {
            ctx.saveGState()
            ctx.addEllipse(in: bubble)
            ctx.clip()
            let grad = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: bubbleGradientColors as CFArray, locations: [0.00, 0.40, 1.0])!
            ctx.drawRadialGradient(grad,
                                   startCenter: CGPoint(x: bubble.midX, y: bubble.midY),
                                   startRadius: bubble.width*0.02,
                                   endCenter: CGPoint(x: bubble.midX, y: bubble.midY),
                                   endRadius: bubble.width*0.5,
                                   options: [])
            ctx.restoreGState()
        }


        let img = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return img
    }

    func setupScene() {
        let scene = SCNScene()
        let sphere = SCNSphere(radius: 1)
        sphere.segmentCount = 130

        let gradientImage = makeGradientTexture()
        sphere.firstMaterial?.diffuse.contents = gradientImage
        sphere.firstMaterial?.lightingModel = .physicallyBased
        sphere.firstMaterial?.roughness.contents = 0.80//控制圆球高亮部分
        sphere.firstMaterial?.metalness.contents = 0.01
        sphere.firstMaterial?.specular.contents = UIColor(red: 180/255, green: 200/255, blue: 240/255, alpha: 0.12) // 不要纯白
        sphere.firstMaterial?.shininess = 0.03
        sphere.firstMaterial?.isDoubleSided = false
        //scene.background.contents = UIColor.clear//控制圆球底部的颜色-----------------------------
        scene.background.contents = makeAppBackgroundGradientImage()
        func makeAppBackgroundGradientImage() -> UIImage {
            let size = CGSize(width: 1000, height: 1000) // 跟你的球体/SceneView 尺寸接近或大一点
            let renderer = UIGraphicsImageRenderer(size: size)
            return renderer.image { ctx in
                let colors = [
                    UIColor(red: 220/255, green: 225/255, blue: 230/255, alpha: 1).cgColor,
                    UIColor(red: 200/255, green: 215/255, blue: 225/255, alpha: 1).cgColor,
                    UIColor(red: 186/255, green: 208/255, blue: 192/255, alpha: 1).cgColor
                ]
                let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: [0.0, 0.5, 1.0])!
                ctx.cgContext.drawLinearGradient(
                    gradient,
                    start: CGPoint(x: 0, y: 0),
                    end: CGPoint(x: size.width, y: size.height),
                    options: []
                )
            }
        }
        
        let sphereNode = SCNNode(geometry: sphere)
        scene.rootNode.addChildNode(sphereNode)

        // 主光源（高色温）------------------
        let light = SCNLight()
        light.type = .omni
        light.intensity = 300//控制高光位置，↓数值越大，中心高光越白，越爆
        light.temperature = 7350
        let lightNode = SCNNode()
        lightNode.light = light
        lightNode.position = SCNVector3(2.4, 4, 9)
        scene.rootNode.addChildNode(lightNode)

        // 辅助冷光
        let blueLight = SCNLight()
        blueLight.type = .omni
        blueLight.intensity = 280
        blueLight.temperature = 8300
        let blueNode = SCNNode()
        blueNode.light = blueLight
        blueNode.position = SCNVector3(-2, -4, 7)
        scene.rootNode.addChildNode(blueNode)

        // 环境光
        let ambient = SCNLight()
        ambient.type = .ambient
        ambient.intensity = 10
        let ambientNode = SCNNode()
        ambientNode.light = ambient
        scene.rootNode.addChildNode(ambientNode)

        // 相机
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(0, 0, 2.0)
        scene.rootNode.addChildNode(cameraNode)

        self.scene = scene
        self.sphereNode = sphereNode
    }
}


//======================================================
// MARK: - 4. 空心轨道滑杆
//======================================================

struct SliderView1: View {

    @Binding var sliderValue:   Double
    @Binding var selectedStyle: Int
    @Binding var lastHapticStep: Int
    let styles: [String]
    var hapticStrength: Double

    @State private var animatePulse = false
    @State private var dragOffset: CGFloat = 0
    @State private var isDragging: Bool = false
    // 动画状态
    @State private var knobScale: CGFloat = 1.0
    @State private var knobShadowRadius: CGFloat = 2.0
    @State private var trackScale: CGFloat = 1.0
    @State private var trackHighlight: Double = 0.0

    private let impactGen  = UIImpactFeedbackGenerator(style: .light)
    private let trackWidth: CGFloat = 240
    private let trackHeight: CGFloat = 13
    private let trackCorner: CGFloat = 11
    private let knobWidth: CGFloat = 16
    private let sidePadding: CGFloat = 8
    private var knobTravel: CGFloat { trackWidth - knobWidth - sidePadding }

    var body: some View {
        ZStack(alignment: .leading) {
            // --- 轨道 ---
            RoundedRectangle(cornerRadius: trackCorner)
                .fill(
                    LinearGradient(
                        gradient: Gradient(stops: [
                            .init(color: Color(red: 236/255, green: 246/255, blue: 255/255).opacity(0.72 + 0.16*trackHighlight), location: 0.0),
                            .init(color: Color(red: 180/255, green: 202/255, blue: 236/255).opacity(0.69 + 0.11*trackHighlight), location: 0.57),
                            .init(color: Color(red: 145/255, green: 175/255, blue: 210/255).opacity(0.88 + 0.12*trackHighlight), location: 1.0)
                        ]),
                        startPoint: .top,
                        endPoint: .bottom
                    )
                )
                .overlay(
                    RoundedRectangle(cornerRadius: trackCorner)
                        .stroke(
                            LinearGradient(
                                gradient: Gradient(colors: [
                                    Color.white.opacity(0.65 + 0.18*trackHighlight),
                                    Color.white.opacity(0.11 + 0.08*trackHighlight)
                                ]),
                                startPoint: .top,
                                endPoint: .bottom
                            ),
                            lineWidth: 1.0
                        )
                        .blur(radius: 0.3)
                        .offset(y: -1)
                )
                .background(
                    RoundedRectangle(cornerRadius: trackCorner)
                        .stroke(Color.white.opacity(0.18 + 0.10*trackHighlight), lineWidth: 2.2)
                        .blur(radius: 3.5 + 3.0*trackHighlight)
                        .offset(y: -2)
                )
                .background(
                    RoundedRectangle(cornerRadius: trackCorner)
                        .stroke(
                            LinearGradient(
                                gradient: Gradient(colors: [
                                    Color(red: 200/255, green: 220/255, blue: 255/255).opacity(0.19 + 0.14*trackHighlight),
                                    .clear
                                ]),
                                startPoint: .top,
                                endPoint: .bottom
                            ),
                            lineWidth: 2.2
                        )
                        .blur(radius: 3.0 + 2.0*trackHighlight)
                        .offset(y: -2.5)
                )
                .shadow(color: Color(red: 180/255, green: 210/255, blue: 255/255).opacity(0.08 + 0.08*trackHighlight), radius: 13 + 4*trackHighlight, x: 0, y: 5)
                .shadow(color: Color.black.opacity(0.07 + 0.04*trackHighlight), radius: 7 + 2*trackHighlight, x: 0, y: 2)
                .frame(width: trackWidth, height: trackHeight)

            // 拖尾 Capsule
            Capsule()
                .fill(
                    LinearGradient(
                        gradient: Gradient(colors: [
                            Color(red: 190/255, green: 220/255, blue: 250/255).opacity(0.10 + 0.07*trackHighlight),
                            Color(red: 170/255, green: 210/255, blue: 240/255).opacity(0.07 + 0.05*trackHighlight),
                            .clear
                        ]),
                        startPoint: .leading,
                        endPoint: .trailing
                    )
                )
                .frame(
                    width: max(0, min(dragOffset + 4, 140)),
                    height: 7
                )
                .offset(
                    x: min((dragOffset + knobWidth/2), trackWidth - knobWidth/2),
                    y: 3.5
                )
                .opacity(dragOffset > 0 ? 0.22 + 0.10*trackHighlight : 0)
                .animation(.easeOut(duration: 0.22), value: dragOffset)

            // --- 新滑块 ---
            knob
                .scaleEffect(knobScale)
                .shadow(
                    color: Color(red: 120/255, green: 170/255, blue: 255/255).opacity(isDragging ? 0.22 : 0.13),
                    radius: knobShadowRadius * (isDragging ? 1.7 : 1.0),
                    x: 0, y: isDragging ? 2.2 : 1.2
                )
                .offset(x: CGFloat(sliderValue) * (trackWidth - knobWidth))
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            let x = max(0, min(value.location.x - knobWidth/2, trackWidth - knobWidth))
                            sliderValue = Double(x / (trackWidth - knobWidth))
                            let step = Int(sliderValue * 20)
                            if step != lastHapticStep {
                                lastHapticStep = step
                                impactGen.impactOccurred()
                            }
                            let idx = Int((sliderValue * Double(styles.count - 1)).rounded())
                            if idx != selectedStyle {
                                selectedStyle = idx
                                HapticBank.patterns[idx].play(strength: hapticStrength)
                            }
                            dragOffset = x
                            if !isDragging {
                                isDragging = true
                                withAnimation(.interactiveSpring(response: 0.28, dampingFraction: 0.65, blendDuration: 0.12)) {
                                    knobScale = 1.19
                                    knobShadowRadius = 4.7
                                    trackScale = 1.04
                                    trackHighlight = 1.0
                                }
                            }
                        }
                        .onEnded { _ in
                            isDragging = false
                            withAnimation(.easeOut(duration: 0.17)) {
                                dragOffset = 0
                            }
                            withAnimation(.interactiveSpring(response: 0.44, dampingFraction: 0.71, blendDuration: 0.16)) {
                                knobScale = 1.0
                                knobShadowRadius = 2.0
                                trackScale = 1.0
                                trackHighlight = 0.0
                            }
                        }
                )
        }
        .frame(width: trackWidth, height: max(knobWidth, trackHeight))
        .scaleEffect(trackScale)
        .animation(.interactiveSpring(response: 0.33, dampingFraction: 0.72, blendDuration: 0.12), value: trackScale)
    }

    private var knob: some View {
        ZStack {
            // 外描边 + 多层渐变光泽
            Circle()
                .stroke(
                    LinearGradient(
                        gradient: Gradient(colors: [
                            Color.white.opacity(0.98),
                            Color(red: 140/255, green: 170/255, blue: 255/255).opacity(0.23),
                            Color(red: 120/255, green: 200/255, blue: 255/255).opacity(0.18),
                            Color(red: 90/255, green: 120/255, blue: 200/255).opacity(0.13)
                        ]),
                        startPoint: .topLeading,
                        endPoint: .bottomTrailing
                    ),
                    lineWidth: 1.8
                )
                .frame(width: knobWidth, height: knobWidth)
                .shadow(color: .white.opacity(0.13), radius: 2.7, x: 0, y: -2.1)

            // 防滑波纹（在同心波纹下方）
            ForEach(1..<5, id: \.self) { i in
                Circle()
                    .stroke(
                        Color.white.opacity(0.12 - 0.015 * Double(i)),
                        lineWidth: 0.75 - 0.13 * Double(i)
                    )
                    .frame(width: knobWidth * (0.45 + 0.12 * CGFloat(i)), height: knobWidth * (0.45 + 0.12 * CGFloat(i)))
            }

            // 主体径向渐变（优化为中心偏蓝/四周冷白/立体光泽）
            Circle()
                .fill(
                    RadialGradient(
                        gradient: Gradient(stops: [
                            .init(color: Color(red: 170/255, green: 195/255, blue: 250/255).opacity(0.96), location: 0.06),
                            .init(color: Color(red: 190/255, green: 220/255, blue: 255/255).opacity(0.91), location: 0.36),
                            .init(color: Color(red: 218/255, green: 229/255, blue: 245/255).opacity(0.91), location: 0.70),
                            .init(color: Color(red: 165/255, green: 180/255, blue: 230/255).opacity(0.89), location: 1.0)
                        ]),
                        center: .init(x: 0.23, y: 0.18),
                        startRadius: 0.7, endRadius: knobWidth / 1.19
                    )
                )
                .frame(width: knobWidth, height: knobWidth)
                .shadow(color: Color.white.opacity(0.13), radius: 1.3, x: 0, y: -1.2)
                // 柔和内光
                .overlay(
                    Circle()
                        .stroke(
                            RadialGradient(
                                gradient: Gradient(colors: [
                                    Color.white.opacity(0.19),
                                    Color.white.opacity(0.01)
                                ]),
                                center: .center,
                                startRadius: 0,
                                endRadius: knobWidth*0.56
                            ),
                            lineWidth: 2.7
                        )
                        .blur(radius: 0.8)
                )
                // 细腻轮廓内阴影
                .overlay(
                    Circle()
                        .stroke(
                            LinearGradient(
                                gradient: Gradient(colors: [
                                    Color.black.opacity(0.09),
                                    Color.white.opacity(0.01)
                                ]),
                                startPoint: .bottom,
                                endPoint: .top
                            ),
                            lineWidth: 0.7
                        )
                        .blur(radius: 0.24)
                )

            // 顶部高光玻璃反射
            Ellipse()
                .fill(Color.white.opacity(0.53))
                .frame(width: knobWidth * 0.47, height: knobWidth * 0.15)
                .offset(x: -knobWidth*0.17, y: -knobWidth*0.36)
                .blur(radius: 0.17)
            // 顶部窄紫色椭圆
            Ellipse()
                .fill(Color(red: 200/255, green: 170/255, blue: 255/255).opacity(0.25))
                .frame(width: knobWidth * 0.23, height: knobWidth * 0.07)
                .offset(x: knobWidth*0.06, y: -knobWidth*0.24)
            // 侧面高光弧
            Capsule()
                .fill(
                    LinearGradient(
                        gradient: Gradient(colors: [
                            Color.white.opacity(0.09), Color.white.opacity(0.01)
                        ]),
                        startPoint: .top,
                        endPoint: .bottom
                    )
                )
                .frame(width: knobWidth*0.19, height: knobWidth*0.63)
                .rotationEffect(.degrees(29))
                .offset(x: knobWidth*0.28, y: knobWidth*0.08)
                .blur(radius: 0.23)
            // 同心波纹
            Circle()
                .stroke(
                    Color(red: 181/255, green: 202/255, blue: 226/255)
                        .opacity(0.09),
                    lineWidth: 0.26)
                .frame(width: knobWidth * 0.64, height: knobWidth * 0.64)
            // 底部椭圆阴影更深
            Ellipse()
                .fill(
                    LinearGradient(
                        gradient: Gradient(stops: [
                            .init(color: Color(red: 120/255, green: 170/255, blue: 255/255).opacity(0.28), location: 0.0),
                            .init(color: Color.black.opacity(0.17), location: 0.62),
                            .init(color: Color.black.opacity(0.00), location: 1.0)
                        ]),
                        startPoint: .top,
                        endPoint: .bottom
                    )
                )
                .frame(width: knobWidth * 0.41, height: knobWidth * 0.14)
                .offset(y: knobWidth * 0.34)
                .blur(radius: 0.8)
            // 内部柔和高光
            Circle()
                .stroke(
                    RadialGradient(
                        gradient: Gradient(colors: [
                            Color.white.opacity(0.23),
                            Color.white.opacity(0.01)
                        ]),
                        center: .init(x: 0.24, y: 0.19),
                        startRadius: 0,
                        endRadius: knobWidth*0.45
                    ),
                    lineWidth: 0.9
                )
                .blur(radius: 0.18)
        }
        .shadow(color: Color.white.opacity(0.19), radius: 1.7, x: 0, y: -1.2)
        .shadow(color: Color.black.opacity(0.13), radius: 2.2, x: 0, y: 2.2)
        .background(
            // 轮廓外部光晕
            Circle()
                .fill(
                    RadialGradient(
                        gradient: Gradient(colors: [
                            Color.white.opacity(0.10),
                            Color.white.opacity(0.00)
                        ]),
                        center: .center,
                        startRadius: knobWidth*0.6,
                        endRadius: knobWidth*1.1
                    )
                )
                .frame(width: knobWidth*1.6, height: knobWidth*1.6)
        )
    }
}

//======================================================
// MARK: - 5. 预览
//======================================================
#Preview {
    ContentView()
}

